﻿#include "chatitemwidget.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QPainter>
#include <QStyleOption>
#include <private/qlabel_p.h>
#include "emotionresource.h"
#include "imageviewer.h"

TextLabel::TextLabel(const QString &text, QWidget *parent) : QLabel(parent)
{
    setTextFormat(Qt::RichText);
    setWordWrap(true);
    setTextInteractionFlags(Qt::TextSelectableByMouse);
    QString newContent = text;
    if(!newContent.isEmpty())
    {
        setText(" ");
        QRegExp rx(QLatin1String("\\[([\\x4e00-\\x9fa5\\w]+)\\]"));
        rx.setMinimal(true);
        int pos = 0;
        auto emotions = EmotionResource::instance();
        auto document = reinterpret_cast<const QLabelPrivate *>(qGetPtrHelper(d_ptr))->control->document();
        /*auto option = document->defaultTextOption();
        option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
        document->setDefaultTextOption(option);*/
        while ((pos = rx.indexIn(newContent, pos)) != -1)
        {
            QString emotionName = rx.cap(1);
            int length = rx.matchedLength();
            if(emotions->containsName(emotionName))
            {
                if(!document->resource(QTextDocument::ImageResource, emotionName).isValid())
                {
                    QPixmap pix = EmotionResource::instance()->findByName(emotionName);
                    if(!pix.isNull())
                        document->addResource(QTextDocument::ImageResource, emotionName, pix);
                }
                const QString toReplace = QLatin1String("<img src=\"") + emotionName.toHtmlEscaped() + QLatin1String("\" />");
                newContent.replace(pos, rx.matchedLength(), toReplace);
                pos += toReplace.length();
            }
            else
                pos += length;
        }
    }
    setText(newContent);
    setMouseTracking(false);
}

bool TextLabel::hasHeightForWidth() const
{
    return QLabel::hasHeightForWidth();
}

int TextLabel::heightForWidth(int w) const
{
    return QLabel::heightForWidth(w);
}

ChatItemWidget::ChatItemWidget(const bool from, const QVariant &display, const QPixmap &pixmap, const QString &extraText, QWidget *parent) : QWidget(parent)
{
    setAutoFillBackground(true);

    icon = new QLabel(this);
    icon->setPixmap(pixmap);
    icon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    int topMargin = 25 - (pixmap.height() + 1) / 2;
    if(topMargin > 0)
    {
        //保持中心点在高度25的位置
        icon->setStyleSheet("margin-top:" + QString::number(topMargin) + "px");
    }

    if(display.type() == QVariant::String)
        content = new TextLabel(display.toString(), this);
    else {
        content = new QLabel(this);
        content->setPixmap(display.value<QPixmap>());
        content->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    }
    extra = new QLabel(this);
    extra->setTextFormat(Qt::PlainText);
    extra->setWordWrap(false);
    extra->setTextInteractionFlags(Qt::NoTextInteraction);
    if(!from) {
        //我发的 extra是状态
        extra->setStyleSheet("font-size: 10px");
        auto boxLayout = new QHBoxLayout(this);
        boxLayout->addSpacerItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
        boxLayout->addWidget(extra, 0, Qt::AlignCenter);
        boxLayout->addWidget(content, 0, Qt::AlignRight | Qt::AlignVCenter);
        boxLayout->addWidget(icon, 0, Qt::AlignTop);
        boxLayout->setSpacing(0);
        content->setStyleSheet("QLabel{border-image: url(:/gui/chatto_bg_normal.9.png) 40 32 18 18 repeat;"
                    "border: 20px solid black;"
                    "border-top: 40px;"
                    "border-right: 32px;"
                    "border-bottom: 18px;"
                    "border-left: 18px;"
                    "padding-top: -24px}");
    }
    else {
        //别人发的 extra是名字
        auto gridLayout = new QGridLayout(this);
        //第一行
        gridLayout->addWidget(extra, 0, 0, 1, -1, Qt::AlignLeft | Qt::AlignVCenter);
        extra->setText(extraText);
        extra->setStyleSheet("font-size: 10px; margin-left:10px");
        //第二行
        gridLayout->addWidget(icon, 1, 0, Qt::AlignTop);
        gridLayout->addWidget(content, 1, 1, Qt::AlignLeft | Qt::AlignVCenter);
        gridLayout->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum), 1, 2);
        gridLayout->setSpacing(0);
        content->setStyleSheet("QLabel{border-image: url(:/gui/chatfrom_bg_normal.9.png) 40 18 18 32 repeat;\
                    border: 20px solid black;\
                    border-top: 40px;\
                    border-right: 18px;\
                    border-bottom: 18px;\
                    border-left: 32px;\
                    padding-top: -24px}");
    }
    connect(this, &ChatItemWidget::contentDoubleClicked, this, &ChatItemWidget::showOriginal, Qt::QueuedConnection);
}

void ChatItemWidget::setDisplay(const QVariant &display, const QVariant &edit, const QString &extraText)
{
    if(display.type() == QVariant::Pixmap)
    {
        content->setPixmap(display.value<QPixmap>());
        if(edit.type() == QVariant::Pixmap && !edit.isNull())
        {
            original = edit;
            content->setCursor(Qt::PointingHandCursor);
        }
    }
    extra->setText(extraText);
}

void ChatItemWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
    if(content->geometry().contains(event->pos()) &&
            original.type() == QVariant::Pixmap && !original.isNull())
    {
        event->accept();
        emit contentDoubleClicked();
    }
    QWidget::mouseDoubleClickEvent(event);
}

void ChatItemWidget::paintEvent(QPaintEvent *)
{
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

void ChatItemWidget::showOriginal()
{
    ImageViewer viewer;
    viewer.setPixmap(original.value<QPixmap>());
    viewer.exec();
}
